﻿#!/usr/bin/python
# -*- coding: utf-8 -*-

''' attribVarsSLASLA.py

Module permettant d'attribuer les variables à un noeud programme, après avoir effectué un parsing.

2009-2010, Elias Capito et Jonathan Neuhaus, HE-Arc

'''

import AST
from AST import addToClass
from parserSLA import parserSLA

# Pile permettant de stocker les liste des variables des noeuds programmes imbriqué 
stack = []

# Opération par défaut pour un noeud
@addToClass(AST.Node)
def attrib(self):
	# Parcours des enfants du noeud
	for c in self.children:
		c.attrib()

# Opération si c'est un noeud programme
@addToClass(AST.ProgramNode)
def attrib(self):
	# Ajoute la liste des variables du noeud programme à la pile
	stack.append(self.vars)

	for c in self.children:
		c.attrib()

	stack.pop()
	
# Opération si c'est un noeud de définition de fonction
@addToClass(AST.FuncDefNode)
def attrib(self):
	# Défini que la pile est une variable globale
	global stack
	# Crée une pile temporaire de la pile actuelle
	tmpStack = stack[:]
	# Vide la pile 
	del stack[:]
	
	# On ajoute à la liste tous les paramètres de la fonctions
	stack.append(list())
	for p in self.funcParams:
		stack[-1].append(p)
		
	for c in self.children:
		c.attrib()
		
	stack.pop()
	
	# Si la pile est vide on remet son contenu avant d'entrer dans le noeud de la fonction de définition
	if(len(stack)==0):
		stack = tmpStack[:]
		
# Opération si c'est un noeud token (Noeud contenant les variables)
@addToClass(AST.TokenNode)
def attrib(self):
	try:
		# On regarde si c'est un nombre
		int(self.tok)
	except:
		# Sinon on test que ce n'est pas un caractère avec des guillements simple
		if self.tok.find('\'')==-1:
			# On attribue la variable à un noeud programme
			attribVar(self.tok)


# Fonction qui permet d'attribuer une variable à un noeud programme
def attribVar(var):
	#Si la variable n'est pas attribuée à un noeud programme parent, on l'ajoute au dernier noeud programme
	if checkVarNotInProg(var):
		stack[-1].append(var)

# Fonction qui permet de contrôler si la variable est déjà attribuée à un noeud programme parent
def checkVarNotInProg(var):
	for p in stack:
		if var in p:
			return False
	return True

# Fonction permettant d'attribuer une variable à un noeud programme
def attribVarsSLA(program):
	parser = parserSLA(program)
	parser.attrib()
	return parser

if __name__ == "__main__":
	import sys
	try:
		prog = file(sys.argv[1]).read()
		result = attribVars(prog)
		print result
		import os
		graph = result.makegraphicaltree()
		name = os.path.splitext(sys.argv[1])[0]+'-vars-ast.pdf'
		graph.write_pdf(name) 
		print "L'arbre syntaxique des variables atribuees a ete genere sous ce nom: ", name
	except IOError: 
		print "*** ERREUR : Le module attribSLA n'a pas trouve le fichier ***"	